/* Verwandlung Online Judge - A cross-platform judge online system
 * Copyright (C) 2018 Haozhe Xie <cshzxie@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *                              _ooOoo_
 *                             o8888888o
 *                             88" . "88
 *                             (| -_- |)
 *                             O\  =  /O
 *                          ____/`---'\____
 *                        .'  \\|     |//  `.
 *                       /  \\|||  :  |||//  \
 *                      /  _||||| -:- |||||-  \
 *                      |   | \\\  -  /// |   |
 *                      | \_|  ''\---/''  |   |
 *                      \  .-\__  `-`  ___/-. /
 *                    ___`. .'  /--.--\  `. . __
 *                 ."" '<  `.___\_<|>_/___.'  >'"".
 *                | | :  `- \`.;`\ _ /`;.`/ - ` : | |
 *                \  \ `-.   \_ __\ /__ _/   .-` /  /
 *           ======`-.____`-.___\_____/___.-`____.-'======
 *                              `=---='
 *
 *                          HERE BE BUDDHA
 *
 */
package cn.gowss.judger.application;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import cn.gowss.judger.mapper.JudgerMapper;
import cn.gowss.judger.mapper.LanguageMapper;
import cn.gowss.judger.messenger.MessageSender;
import cn.gowss.judger.model.Judger;
import cn.gowss.judger.model.Language;

/**
 * 应用程序心跳.
 * 用于向Web模块发送Keep-Alive信息.
 *
 * @author Haozhe Xie
 */
@Component
public class ApplicationHeartbeat implements Runnable {
	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		if ( !isIdentityValid() ) {
			LOGGER.error("Unauthorized: Please check your username and password.");
			System.exit(-1);
		}
		Calendar calendar = Calendar.getInstance();
		long currentTime = calendar.getTimeInMillis();

		Map<String, Object> mapMessage = new HashMap<>();
		mapMessage.put("event", "KeepAlive");
		mapMessage.put("judgerName", this.judgerName);
		mapMessage.put("description", judgerLanguageSlug);
		mapMessage.put("heartbeatTime", currentTime);
		Judger judger = judgerMapper.getJudgerUsingName(judgerName);
		if(judger == null) {
			judger = new Judger();
			judger.setId(UUID.randomUUID().toString().replace("-",""));
			judger.setName(judgerName);
			judger.setDescription(this.judgerLanguageSlug);
			judger.setStatus(1);
			judgerMapper.insertJudger(judger);
		}else {
			judger.setName(judgerName);
			judger.setDescription(this.judgerLanguageSlug);
			judger.setStatus(1);
			judgerMapper.updateJudger(judger);
		}
		messageSender.sendMessage(mapMessage);
		LOGGER.info("Heartbeat sent to the web server.");
	}

	/**
	 * 检查评测机的身份信息是否有效.
	 * @return 评测机的身份信息是否有效
	 */
	private boolean isIdentityValid() {
		//TODO 验证测评机是否有效
		String[] languageSlugs = judgerLanguageSlug.split(",");
		for (String languageSlug : languageSlugs) {
			Language language = languageMapper.getLanguageUsingSlug(languageSlug.trim());
			if(language == null) {
				return false;
			}
		}
		return true;
	}


	/**
	 * 评测机身份信息.
	 * 评测机的语言.
	 */
	@Value("${judger.language_slug}")
	private String judgerLanguageSlug;

	@Value("${judger.judger_name}")
	private String judgerName;

	/**
	 * 自动注入的MessageSender对象.
	 * 用于向消息队列发送消息.
	 */
	@Autowired
	private MessageSender messageSender;

	/**
	 * 自动注入的JudgerMapper对象.
	 * 用于验证评测机的身份信息.
	 */
	@Autowired
	private JudgerMapper judgerMapper;

	/**
	 * 自动注入LanguageMapper
	 * 用于写入评测机的身份信息.
	 */
	@Autowired
	private LanguageMapper languageMapper;

	/**
	 * 日志记录器.
	 */
	private static final Logger LOGGER = LogManager.getLogger(ApplicationHeartbeat.class);
}
